package cn.edu.scau.cmi.ema.service;

import java.util.List;
import java.util.Set;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;


import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.Session;
import cn.edu.scau.cmi.ema.dao.*;
import cn.edu.scau.cmi.ema.domain.*;
import cn.edu.scau.cmi.ema.util.CmiSqlUtil;
import cn.edu.scau.cmi.ema.domain.base.CmiPagination;
import cn.edu.scau.cmi.ema.service.base.CmiEmaService;

import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import javax.persistence.Query;
import java.util.Iterator;
@Service("UnitService")
@Transactional

public class UnitServiceImpl extends CmiEmaService implements UnitService {
	public UnitServiceImpl() {
	}

	@Transactional
	public Unit saveUnit(Unit unit) {
		Set<Additiveaddress> existingAdditiveaddresssForUnit = new HashSet<Additiveaddress>();
		Set<Detectdetail> existingDetectdetailsForUnit = new HashSet<Detectdetail>();
		Set<Detectfeature> existingDetectfeaturesForUnit = new HashSet<Detectfeature>();
		Set<Detectstandard> existingDetectstandardsForUnit = new HashSet<Detectstandard>();
		Set<Expire> existingExpiresForUnit = new HashSet<Expire>();
		Set<Featurestandard> existingFeaturestandardsForUnit = new HashSet<Featurestandard>();
		Set<Foodbatch> existingFoodbatchsForUnit = new HashSet<Foodbatch>();
		Set<Foodbatchfiller> existingFoodbatchfillersForUnit = new HashSet<Foodbatchfiller>();
		Set<Foodsaleaddress> existingFoodsaleaddresssForUnit = new HashSet<Foodsaleaddress>();
		Set<Materialaddress> existingMaterialaddresssForUnit = new HashSet<Materialaddress>();
		Set<Packingmethod> existingPackingmethodsForUnit = new HashSet<Packingmethod>();
		Set<Processmethod> existingProcessmethodsForUnit = new HashSet<Processmethod>();
		Set<Purchaseadditive> existingPurchaseadditivesForUnit = new HashSet<Purchaseadditive>();
		Set<Purchasematerial> existingPurchasematerialsForUnit = new HashSet<Purchasematerial>();

		Set<Additiveaddress> selectedAdditiveaddresssForUnit = unit.getAdditiveaddresssForUnit();
		Set<Detectdetail> selectedDetectdetailsForUnit = unit.getDetectdetailsForUnit();
		Set<Detectfeature> selectedDetectfeaturesForUnit = unit.getDetectfeaturesForUnit();
		Set<Detectstandard> selectedDetectstandardsForUnit = unit.getDetectstandardsForUnit();
		Set<Expire> selectedExpiresForUnit = unit.getExpiresForUnit();
		Set<Featurestandard> selectedFeaturestandardsForUnit = unit.getFeaturestandardsForUnit();
		Set<Foodbatch> selectedFoodbatchsForUnit = unit.getFoodbatchsForUnit();
		Set<Foodbatchfiller> selectedFoodbatchfillersForUnit = unit.getFoodbatchfillersForUnit();
		Set<Foodsaleaddress> selectedFoodsaleaddresssForUnit = unit.getFoodsaleaddresssForUnit();
		Set<Materialaddress> selectedMaterialaddresssForUnit = unit.getMaterialaddresssForUnit();
		Set<Packingmethod> selectedPackingmethodsForUnit = unit.getPackingmethodsForUnit();
		Set<Processmethod> selectedProcessmethodsForUnit = unit.getProcessmethodsForUnit();
		Set<Purchaseadditive> selectedPurchaseadditivesForUnit = unit.getPurchaseadditivesForUnit();
		Set<Purchasematerial> selectedPurchasematerialsForUnit = unit.getPurchasematerialsForUnit();

		if (unit.getId() == null) {

			Unit existingUnit = unitDAO.findUnitByPhysicalPrimaryKey(unit.getName(), unit.getType());

			if (isEquals(unit, existingUnit)) {
				return existingUnit;
			}

			unit = unitDAO.store(unit);
			unitDAO.flush();

			for (Additiveaddress relatedAdditiveaddress : selectedAdditiveaddresssForUnit) {
				relatedAdditiveaddress.setUnit(unit);
				additiveaddressDAO.store(relatedAdditiveaddress);
			}
			for (Detectdetail relatedDetectdetail : selectedDetectdetailsForUnit) {
				relatedDetectdetail.setUnit(unit);
				detectdetailDAO.store(relatedDetectdetail);
			}
			for (Detectfeature relatedDetectfeature : selectedDetectfeaturesForUnit) {
				relatedDetectfeature.setUnit(unit);
				detectfeatureDAO.store(relatedDetectfeature);
			}
			for (Detectstandard relatedDetectstandard : selectedDetectstandardsForUnit) {
				relatedDetectstandard.setUnit(unit);
				detectstandardDAO.store(relatedDetectstandard);
			}
			for (Expire relatedExpire : selectedExpiresForUnit) {
				relatedExpire.setUnit(unit);
				expireDAO.store(relatedExpire);
			}
			for (Featurestandard relatedFeaturestandard : selectedFeaturestandardsForUnit) {
				relatedFeaturestandard.setUnit(unit);
				featurestandardDAO.store(relatedFeaturestandard);
			}
			for (Foodbatch relatedFoodbatch : selectedFoodbatchsForUnit) {
				relatedFoodbatch.setUnit(unit);
				foodbatchDAO.store(relatedFoodbatch);
			}
			for (Foodbatchfiller relatedFoodbatchfiller : selectedFoodbatchfillersForUnit) {
				relatedFoodbatchfiller.setUnit(unit);
				foodbatchfillerDAO.store(relatedFoodbatchfiller);
			}
			for (Foodsaleaddress relatedFoodsaleaddress : selectedFoodsaleaddresssForUnit) {
				relatedFoodsaleaddress.setUnit(unit);
				foodsaleaddressDAO.store(relatedFoodsaleaddress);
			}
			for (Materialaddress relatedMaterialaddress : selectedMaterialaddresssForUnit) {
				relatedMaterialaddress.setUnit(unit);
				materialaddressDAO.store(relatedMaterialaddress);
			}
			for (Packingmethod relatedPackingmethod : selectedPackingmethodsForUnit) {
				relatedPackingmethod.setUnit(unit);
				packingmethodDAO.store(relatedPackingmethod);
			}
			for (Processmethod relatedProcessmethod : selectedProcessmethodsForUnit) {
				relatedProcessmethod.setUnit(unit);
				processmethodDAO.store(relatedProcessmethod);
			}
			for (Purchaseadditive relatedPurchaseadditive : selectedPurchaseadditivesForUnit) {
				relatedPurchaseadditive.setUnit(unit);
				purchaseadditiveDAO.store(relatedPurchaseadditive);
			}
			for (Purchasematerial relatedPurchasematerial : selectedPurchasematerialsForUnit) {
				relatedPurchasematerial.setUnit(unit);
				purchasematerialDAO.store(relatedPurchasematerial);
			}
		} else {
			Unit existingUnit = unitDAO.findUnitByPrimaryKey(unit.getId());

			existingAdditiveaddresssForUnit = existingUnit.getAdditiveaddresssForUnit();
			existingDetectdetailsForUnit = existingUnit.getDetectdetailsForUnit();
			existingDetectfeaturesForUnit = existingUnit.getDetectfeaturesForUnit();
			existingDetectstandardsForUnit = existingUnit.getDetectstandardsForUnit();
			existingExpiresForUnit = existingUnit.getExpiresForUnit();
			existingFeaturestandardsForUnit = existingUnit.getFeaturestandardsForUnit();
			existingFoodbatchsForUnit = existingUnit.getFoodbatchsForUnit();
			existingFoodbatchfillersForUnit = existingUnit.getFoodbatchfillersForUnit();
			existingFoodsaleaddresssForUnit = existingUnit.getFoodsaleaddresssForUnit();
			existingMaterialaddresssForUnit = existingUnit.getMaterialaddresssForUnit();
			existingPackingmethodsForUnit = existingUnit.getPackingmethodsForUnit();
			existingProcessmethodsForUnit = existingUnit.getProcessmethodsForUnit();
			existingPurchaseadditivesForUnit = existingUnit.getPurchaseadditivesForUnit();
			existingPurchasematerialsForUnit = existingUnit.getPurchasematerialsForUnit();

			Set<Additiveaddress> prepareDeleteAdditiveaddresssForUnit = new HashSet<Additiveaddress>();
			Set<Additiveaddress> prepareAddAdditiveaddresssForUnit = new HashSet<Additiveaddress>();

			prepareDeleteAdditiveaddresssForUnit.addAll(selectedAdditiveaddresssForUnit);
			prepareDeleteAdditiveaddresssForUnit.addAll(existingAdditiveaddresssForUnit);

			prepareAddAdditiveaddresssForUnit.addAll(selectedAdditiveaddresssForUnit);
			prepareAddAdditiveaddresssForUnit.addAll(existingAdditiveaddresssForUnit);

			prepareDeleteAdditiveaddresssForUnit.removeAll(selectedAdditiveaddresssForUnit);
			prepareAddAdditiveaddresssForUnit.removeAll(existingAdditiveaddresssForUnit);

			for (Additiveaddress relatedAdditiveaddress : prepareAddAdditiveaddresssForUnit) {
				relatedAdditiveaddress.setUnit(unit);
				additiveaddressDAO.store(relatedAdditiveaddress);
			}

			for (Additiveaddress relatedAdditiveaddress : prepareDeleteAdditiveaddresssForUnit) {
				relatedAdditiveaddress.setUnit(null);
				additiveaddressDAO.store(relatedAdditiveaddress);
			}
			Set<Detectdetail> prepareDeleteDetectdetailsForUnit = new HashSet<Detectdetail>();
			Set<Detectdetail> prepareAddDetectdetailsForUnit = new HashSet<Detectdetail>();

			prepareDeleteDetectdetailsForUnit.addAll(selectedDetectdetailsForUnit);
			prepareDeleteDetectdetailsForUnit.addAll(existingDetectdetailsForUnit);

			prepareAddDetectdetailsForUnit.addAll(selectedDetectdetailsForUnit);
			prepareAddDetectdetailsForUnit.addAll(existingDetectdetailsForUnit);

			prepareDeleteDetectdetailsForUnit.removeAll(selectedDetectdetailsForUnit);
			prepareAddDetectdetailsForUnit.removeAll(existingDetectdetailsForUnit);

			for (Detectdetail relatedDetectdetail : prepareAddDetectdetailsForUnit) {
				relatedDetectdetail.setUnit(unit);
				detectdetailDAO.store(relatedDetectdetail);
			}

			for (Detectdetail relatedDetectdetail : prepareDeleteDetectdetailsForUnit) {
				relatedDetectdetail.setUnit(null);
				detectdetailDAO.store(relatedDetectdetail);
			}
			Set<Detectfeature> prepareDeleteDetectfeaturesForUnit = new HashSet<Detectfeature>();
			Set<Detectfeature> prepareAddDetectfeaturesForUnit = new HashSet<Detectfeature>();

			prepareDeleteDetectfeaturesForUnit.addAll(selectedDetectfeaturesForUnit);
			prepareDeleteDetectfeaturesForUnit.addAll(existingDetectfeaturesForUnit);

			prepareAddDetectfeaturesForUnit.addAll(selectedDetectfeaturesForUnit);
			prepareAddDetectfeaturesForUnit.addAll(existingDetectfeaturesForUnit);

			prepareDeleteDetectfeaturesForUnit.removeAll(selectedDetectfeaturesForUnit);
			prepareAddDetectfeaturesForUnit.removeAll(existingDetectfeaturesForUnit);

			for (Detectfeature relatedDetectfeature : prepareAddDetectfeaturesForUnit) {
				relatedDetectfeature.setUnit(unit);
				detectfeatureDAO.store(relatedDetectfeature);
			}

			for (Detectfeature relatedDetectfeature : prepareDeleteDetectfeaturesForUnit) {
				relatedDetectfeature.setUnit(null);
				detectfeatureDAO.store(relatedDetectfeature);
			}
			Set<Detectstandard> prepareDeleteDetectstandardsForUnit = new HashSet<Detectstandard>();
			Set<Detectstandard> prepareAddDetectstandardsForUnit = new HashSet<Detectstandard>();

			prepareDeleteDetectstandardsForUnit.addAll(selectedDetectstandardsForUnit);
			prepareDeleteDetectstandardsForUnit.addAll(existingDetectstandardsForUnit);

			prepareAddDetectstandardsForUnit.addAll(selectedDetectstandardsForUnit);
			prepareAddDetectstandardsForUnit.addAll(existingDetectstandardsForUnit);

			prepareDeleteDetectstandardsForUnit.removeAll(selectedDetectstandardsForUnit);
			prepareAddDetectstandardsForUnit.removeAll(existingDetectstandardsForUnit);

			for (Detectstandard relatedDetectstandard : prepareAddDetectstandardsForUnit) {
				relatedDetectstandard.setUnit(unit);
				detectstandardDAO.store(relatedDetectstandard);
			}

			for (Detectstandard relatedDetectstandard : prepareDeleteDetectstandardsForUnit) {
				relatedDetectstandard.setUnit(null);
				detectstandardDAO.store(relatedDetectstandard);
			}
			Set<Expire> prepareDeleteExpiresForUnit = new HashSet<Expire>();
			Set<Expire> prepareAddExpiresForUnit = new HashSet<Expire>();

			prepareDeleteExpiresForUnit.addAll(selectedExpiresForUnit);
			prepareDeleteExpiresForUnit.addAll(existingExpiresForUnit);

			prepareAddExpiresForUnit.addAll(selectedExpiresForUnit);
			prepareAddExpiresForUnit.addAll(existingExpiresForUnit);

			prepareDeleteExpiresForUnit.removeAll(selectedExpiresForUnit);
			prepareAddExpiresForUnit.removeAll(existingExpiresForUnit);

			for (Expire relatedExpire : prepareAddExpiresForUnit) {
				relatedExpire.setUnit(unit);
				expireDAO.store(relatedExpire);
			}

			for (Expire relatedExpire : prepareDeleteExpiresForUnit) {
				relatedExpire.setUnit(null);
				expireDAO.store(relatedExpire);
			}
			Set<Featurestandard> prepareDeleteFeaturestandardsForUnit = new HashSet<Featurestandard>();
			Set<Featurestandard> prepareAddFeaturestandardsForUnit = new HashSet<Featurestandard>();

			prepareDeleteFeaturestandardsForUnit.addAll(selectedFeaturestandardsForUnit);
			prepareDeleteFeaturestandardsForUnit.addAll(existingFeaturestandardsForUnit);

			prepareAddFeaturestandardsForUnit.addAll(selectedFeaturestandardsForUnit);
			prepareAddFeaturestandardsForUnit.addAll(existingFeaturestandardsForUnit);

			prepareDeleteFeaturestandardsForUnit.removeAll(selectedFeaturestandardsForUnit);
			prepareAddFeaturestandardsForUnit.removeAll(existingFeaturestandardsForUnit);

			for (Featurestandard relatedFeaturestandard : prepareAddFeaturestandardsForUnit) {
				relatedFeaturestandard.setUnit(unit);
				featurestandardDAO.store(relatedFeaturestandard);
			}

			for (Featurestandard relatedFeaturestandard : prepareDeleteFeaturestandardsForUnit) {
				relatedFeaturestandard.setUnit(null);
				featurestandardDAO.store(relatedFeaturestandard);
			}
			Set<Foodbatch> prepareDeleteFoodbatchsForUnit = new HashSet<Foodbatch>();
			Set<Foodbatch> prepareAddFoodbatchsForUnit = new HashSet<Foodbatch>();

			prepareDeleteFoodbatchsForUnit.addAll(selectedFoodbatchsForUnit);
			prepareDeleteFoodbatchsForUnit.addAll(existingFoodbatchsForUnit);

			prepareAddFoodbatchsForUnit.addAll(selectedFoodbatchsForUnit);
			prepareAddFoodbatchsForUnit.addAll(existingFoodbatchsForUnit);

			prepareDeleteFoodbatchsForUnit.removeAll(selectedFoodbatchsForUnit);
			prepareAddFoodbatchsForUnit.removeAll(existingFoodbatchsForUnit);

			for (Foodbatch relatedFoodbatch : prepareAddFoodbatchsForUnit) {
				relatedFoodbatch.setUnit(unit);
				foodbatchDAO.store(relatedFoodbatch);
			}

			for (Foodbatch relatedFoodbatch : prepareDeleteFoodbatchsForUnit) {
				relatedFoodbatch.setUnit(null);
				foodbatchDAO.store(relatedFoodbatch);
			}
			Set<Foodbatchfiller> prepareDeleteFoodbatchfillersForUnit = new HashSet<Foodbatchfiller>();
			Set<Foodbatchfiller> prepareAddFoodbatchfillersForUnit = new HashSet<Foodbatchfiller>();

			prepareDeleteFoodbatchfillersForUnit.addAll(selectedFoodbatchfillersForUnit);
			prepareDeleteFoodbatchfillersForUnit.addAll(existingFoodbatchfillersForUnit);

			prepareAddFoodbatchfillersForUnit.addAll(selectedFoodbatchfillersForUnit);
			prepareAddFoodbatchfillersForUnit.addAll(existingFoodbatchfillersForUnit);

			prepareDeleteFoodbatchfillersForUnit.removeAll(selectedFoodbatchfillersForUnit);
			prepareAddFoodbatchfillersForUnit.removeAll(existingFoodbatchfillersForUnit);

			for (Foodbatchfiller relatedFoodbatchfiller : prepareAddFoodbatchfillersForUnit) {
				relatedFoodbatchfiller.setUnit(unit);
				foodbatchfillerDAO.store(relatedFoodbatchfiller);
			}

			for (Foodbatchfiller relatedFoodbatchfiller : prepareDeleteFoodbatchfillersForUnit) {
				relatedFoodbatchfiller.setUnit(null);
				foodbatchfillerDAO.store(relatedFoodbatchfiller);
			}
			Set<Foodsaleaddress> prepareDeleteFoodsaleaddresssForUnit = new HashSet<Foodsaleaddress>();
			Set<Foodsaleaddress> prepareAddFoodsaleaddresssForUnit = new HashSet<Foodsaleaddress>();

			prepareDeleteFoodsaleaddresssForUnit.addAll(selectedFoodsaleaddresssForUnit);
			prepareDeleteFoodsaleaddresssForUnit.addAll(existingFoodsaleaddresssForUnit);

			prepareAddFoodsaleaddresssForUnit.addAll(selectedFoodsaleaddresssForUnit);
			prepareAddFoodsaleaddresssForUnit.addAll(existingFoodsaleaddresssForUnit);

			prepareDeleteFoodsaleaddresssForUnit.removeAll(selectedFoodsaleaddresssForUnit);
			prepareAddFoodsaleaddresssForUnit.removeAll(existingFoodsaleaddresssForUnit);

			for (Foodsaleaddress relatedFoodsaleaddress : prepareAddFoodsaleaddresssForUnit) {
				relatedFoodsaleaddress.setUnit(unit);
				foodsaleaddressDAO.store(relatedFoodsaleaddress);
			}

			for (Foodsaleaddress relatedFoodsaleaddress : prepareDeleteFoodsaleaddresssForUnit) {
				relatedFoodsaleaddress.setUnit(null);
				foodsaleaddressDAO.store(relatedFoodsaleaddress);
			}
			Set<Materialaddress> prepareDeleteMaterialaddresssForUnit = new HashSet<Materialaddress>();
			Set<Materialaddress> prepareAddMaterialaddresssForUnit = new HashSet<Materialaddress>();

			prepareDeleteMaterialaddresssForUnit.addAll(selectedMaterialaddresssForUnit);
			prepareDeleteMaterialaddresssForUnit.addAll(existingMaterialaddresssForUnit);

			prepareAddMaterialaddresssForUnit.addAll(selectedMaterialaddresssForUnit);
			prepareAddMaterialaddresssForUnit.addAll(existingMaterialaddresssForUnit);

			prepareDeleteMaterialaddresssForUnit.removeAll(selectedMaterialaddresssForUnit);
			prepareAddMaterialaddresssForUnit.removeAll(existingMaterialaddresssForUnit);

			for (Materialaddress relatedMaterialaddress : prepareAddMaterialaddresssForUnit) {
				relatedMaterialaddress.setUnit(unit);
				materialaddressDAO.store(relatedMaterialaddress);
			}

			for (Materialaddress relatedMaterialaddress : prepareDeleteMaterialaddresssForUnit) {
				relatedMaterialaddress.setUnit(null);
				materialaddressDAO.store(relatedMaterialaddress);
			}
			Set<Packingmethod> prepareDeletePackingmethodsForUnit = new HashSet<Packingmethod>();
			Set<Packingmethod> prepareAddPackingmethodsForUnit = new HashSet<Packingmethod>();

			prepareDeletePackingmethodsForUnit.addAll(selectedPackingmethodsForUnit);
			prepareDeletePackingmethodsForUnit.addAll(existingPackingmethodsForUnit);

			prepareAddPackingmethodsForUnit.addAll(selectedPackingmethodsForUnit);
			prepareAddPackingmethodsForUnit.addAll(existingPackingmethodsForUnit);

			prepareDeletePackingmethodsForUnit.removeAll(selectedPackingmethodsForUnit);
			prepareAddPackingmethodsForUnit.removeAll(existingPackingmethodsForUnit);

			for (Packingmethod relatedPackingmethod : prepareAddPackingmethodsForUnit) {
				relatedPackingmethod.setUnit(unit);
				packingmethodDAO.store(relatedPackingmethod);
			}

			for (Packingmethod relatedPackingmethod : prepareDeletePackingmethodsForUnit) {
				relatedPackingmethod.setUnit(null);
				packingmethodDAO.store(relatedPackingmethod);
			}
			Set<Processmethod> prepareDeleteProcessmethodsForUnit = new HashSet<Processmethod>();
			Set<Processmethod> prepareAddProcessmethodsForUnit = new HashSet<Processmethod>();

			prepareDeleteProcessmethodsForUnit.addAll(selectedProcessmethodsForUnit);
			prepareDeleteProcessmethodsForUnit.addAll(existingProcessmethodsForUnit);

			prepareAddProcessmethodsForUnit.addAll(selectedProcessmethodsForUnit);
			prepareAddProcessmethodsForUnit.addAll(existingProcessmethodsForUnit);

			prepareDeleteProcessmethodsForUnit.removeAll(selectedProcessmethodsForUnit);
			prepareAddProcessmethodsForUnit.removeAll(existingProcessmethodsForUnit);

			for (Processmethod relatedProcessmethod : prepareAddProcessmethodsForUnit) {
				relatedProcessmethod.setUnit(unit);
				processmethodDAO.store(relatedProcessmethod);
			}

			for (Processmethod relatedProcessmethod : prepareDeleteProcessmethodsForUnit) {
				relatedProcessmethod.setUnit(null);
				processmethodDAO.store(relatedProcessmethod);
			}
			Set<Purchaseadditive> prepareDeletePurchaseadditivesForUnit = new HashSet<Purchaseadditive>();
			Set<Purchaseadditive> prepareAddPurchaseadditivesForUnit = new HashSet<Purchaseadditive>();

			prepareDeletePurchaseadditivesForUnit.addAll(selectedPurchaseadditivesForUnit);
			prepareDeletePurchaseadditivesForUnit.addAll(existingPurchaseadditivesForUnit);

			prepareAddPurchaseadditivesForUnit.addAll(selectedPurchaseadditivesForUnit);
			prepareAddPurchaseadditivesForUnit.addAll(existingPurchaseadditivesForUnit);

			prepareDeletePurchaseadditivesForUnit.removeAll(selectedPurchaseadditivesForUnit);
			prepareAddPurchaseadditivesForUnit.removeAll(existingPurchaseadditivesForUnit);

			for (Purchaseadditive relatedPurchaseadditive : prepareAddPurchaseadditivesForUnit) {
				relatedPurchaseadditive.setUnit(unit);
				purchaseadditiveDAO.store(relatedPurchaseadditive);
			}

			for (Purchaseadditive relatedPurchaseadditive : prepareDeletePurchaseadditivesForUnit) {
				relatedPurchaseadditive.setUnit(null);
				purchaseadditiveDAO.store(relatedPurchaseadditive);
			}
			Set<Purchasematerial> prepareDeletePurchasematerialsForUnit = new HashSet<Purchasematerial>();
			Set<Purchasematerial> prepareAddPurchasematerialsForUnit = new HashSet<Purchasematerial>();

			prepareDeletePurchasematerialsForUnit.addAll(selectedPurchasematerialsForUnit);
			prepareDeletePurchasematerialsForUnit.addAll(existingPurchasematerialsForUnit);

			prepareAddPurchasematerialsForUnit.addAll(selectedPurchasematerialsForUnit);
			prepareAddPurchasematerialsForUnit.addAll(existingPurchasematerialsForUnit);

			prepareDeletePurchasematerialsForUnit.removeAll(selectedPurchasematerialsForUnit);
			prepareAddPurchasematerialsForUnit.removeAll(existingPurchasematerialsForUnit);

			for (Purchasematerial relatedPurchasematerial : prepareAddPurchasematerialsForUnit) {
				relatedPurchasematerial.setUnit(unit);
				purchasematerialDAO.store(relatedPurchasematerial);
			}

			for (Purchasematerial relatedPurchasematerial : prepareDeletePurchasematerialsForUnit) {
				relatedPurchasematerial.setUnit(null);
				purchasematerialDAO.store(relatedPurchasematerial);
			}
			unit = unitDAO.store(unit);
			unitDAO.flush();
		}

		additiveaddressDAO.flush();
		detectdetailDAO.flush();
		detectfeatureDAO.flush();
		detectstandardDAO.flush();
		expireDAO.flush();
		featurestandardDAO.flush();
		foodbatchDAO.flush();
		foodbatchfillerDAO.flush();
		foodsaleaddressDAO.flush();
		materialaddressDAO.flush();
		packingmethodDAO.flush();
		processmethodDAO.flush();
		purchaseadditiveDAO.flush();
		purchasematerialDAO.flush();
		return unit;
	}

	public void deleteUnit(Unit unit) {
		unitDAO.remove(unit);
		unitDAO.flush();
	}

	@Transactional
	public void deleteUnits(Set<Integer> deleteUnitsId) {
		Query query = unitDAO.createNamedQuery("deleteUnitsById", -1, -1);
		query.setParameter(1, deleteUnitsId);
		query.executeUpdate();
	}

	@Transactional
	public Set<Unit> loadUnits() {
		return unitDAO.findAllUnits();

	}

	@Transactional
	public Set<Unit> loadReferenceUnits(Set<Unit> units) {
		Iterator<Unit> unitsIterator = units.iterator();
		Set<Unit> referencedUnits = new HashSet<>();
		while (unitsIterator.hasNext()) {
			Unit currentUnit = unitsIterator.next();

			if (!currentUnit.getAdditiveaddresssForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getDetectdetailsForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getDetectfeaturesForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getDetectstandardsForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getExpiresForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getFeaturestandardsForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getFoodbatchsForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getFoodbatchfillersForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getFoodsaleaddresssForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getMaterialaddresssForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getPackingmethodsForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getProcessmethodsForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getPurchaseadditivesForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}

			if (!currentUnit.getPurchasematerialsForUnit().isEmpty()) {
				referencedUnits.add(currentUnit);
				continue;
			}
		}
		return referencedUnits;
	}

	public Set<Unit> loadUnitsByIdSet(Set<Integer> unitIdSet) {

		Iterator<Integer> unitIdIterator = unitIdSet.iterator();
		Set<Unit> unitSet = new HashSet<>();
		while (unitIdIterator.hasNext()) {
			Integer id = unitIdIterator.next();
			Unit currentUnit = unitDAO.findUnitById(id);
			unitSet.add(currentUnit);
		}
		return unitSet;
	}

	@Transactional
	public List<Unit> findAllUnits(Integer startResult, Integer maxRows) {
		return new java.util.ArrayList<Unit>(unitDAO.findAllUnits(startResult, maxRows));
	}

	@Transactional
	public Unit findUnitByPrimaryKey(Integer id) {
		return unitDAO.findUnitByPrimaryKey(id);
	}

	@Transactional
	public Integer countUnits() {
		return ((Long) unitDAO.createQuerySingleResult("select count(o) from Unit o").getSingleResult()).intValue();
	}

	@Transactional
	public Integer countUnits(CmiPagination page) {
		String sql = CmiSqlUtil.createCountHql(page, Unit.class);
		return ((Long) unitDAO.createQuerySingleResult(sql).getSingleResult()).intValue();
	}

	/**
	 * search for name with ajax
	 * 
	 */
	@Transactional
	public Integer countUnitsByName(String queryName) {
		Query query = unitDAO.createNamedQuery("countUnitsByName", -1, -1);
		query.setParameter(1, queryName);
		return new Long((long) query.getSingleResult()).intValue();
	}

	@Transactional
	public Integer countUnitsByDetachedCriteria(CmiPagination page) {
		DetachedCriteria detachedCriteria = CmiSqlUtil.createDetachedCriteria(page, Unit.class);
		Session session = entityManager.unwrap(Session.class);
		detachedCriteria.setProjection(Projections.rowCount());
		return new Long((long) detachedCriteria.getExecutableCriteria(session).uniqueResult()).intValue();
	}

	public Map<String, ?> loadUnitObjectReferencedSet(Unit unit) {
		HashMap<String, Object> objectReferencedSetMap = new HashMap<>();

		Set<Integer> additiveaddresssIds = new HashSet<Integer>();
		for (Additiveaddress obj : unit.getAdditiveaddresssForUnit()) {

			additiveaddresssIds.add(obj.getId());
		}
		objectReferencedSetMap.put("additiveaddresssIds", additiveaddresssIds);
		Set<Integer> detectdetailsIds = new HashSet<Integer>();
		for (Detectdetail obj : unit.getDetectdetailsForUnit()) {

			detectdetailsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("detectdetailsIds", detectdetailsIds);
		Set<Integer> detectfeaturesIds = new HashSet<Integer>();
		for (Detectfeature obj : unit.getDetectfeaturesForUnit()) {

			detectfeaturesIds.add(obj.getId());
		}
		objectReferencedSetMap.put("detectfeaturesIds", detectfeaturesIds);
		Set<Integer> detectstandardsIds = new HashSet<Integer>();
		for (Detectstandard obj : unit.getDetectstandardsForUnit()) {

			detectstandardsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("detectstandardsIds", detectstandardsIds);
		Set<Integer> expiresIds = new HashSet<Integer>();
		for (Expire obj : unit.getExpiresForUnit()) {

			expiresIds.add(obj.getId());
		}
		objectReferencedSetMap.put("expiresIds", expiresIds);
		Set<Integer> featurestandardsIds = new HashSet<Integer>();
		for (Featurestandard obj : unit.getFeaturestandardsForUnit()) {

			featurestandardsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("featurestandardsIds", featurestandardsIds);
		Set<Integer> foodbatchsIds = new HashSet<Integer>();
		for (Foodbatch obj : unit.getFoodbatchsForUnit()) {

			foodbatchsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("foodbatchsIds", foodbatchsIds);
		Set<Integer> foodbatchfillersIds = new HashSet<Integer>();
		for (Foodbatchfiller obj : unit.getFoodbatchfillersForUnit()) {

			foodbatchfillersIds.add(obj.getId());
		}
		objectReferencedSetMap.put("foodbatchfillersIds", foodbatchfillersIds);
		Set<Integer> foodsaleaddresssIds = new HashSet<Integer>();
		for (Foodsaleaddress obj : unit.getFoodsaleaddresssForUnit()) {

			foodsaleaddresssIds.add(obj.getId());
		}
		objectReferencedSetMap.put("foodsaleaddresssIds", foodsaleaddresssIds);
		Set<Integer> materialaddresssIds = new HashSet<Integer>();
		for (Materialaddress obj : unit.getMaterialaddresssForUnit()) {

			materialaddresssIds.add(obj.getId());
		}
		objectReferencedSetMap.put("materialaddresssIds", materialaddresssIds);
		Set<Integer> packingmethodsIds = new HashSet<Integer>();
		for (Packingmethod obj : unit.getPackingmethodsForUnit()) {

			packingmethodsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("packingmethodsIds", packingmethodsIds);
		Set<Integer> processmethodsIds = new HashSet<Integer>();
		for (Processmethod obj : unit.getProcessmethodsForUnit()) {

			processmethodsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("processmethodsIds", processmethodsIds);
		Set<Integer> purchaseadditivesIds = new HashSet<Integer>();
		for (Purchaseadditive obj : unit.getPurchaseadditivesForUnit()) {

			purchaseadditivesIds.add(obj.getId());
		}
		objectReferencedSetMap.put("purchaseadditivesIds", purchaseadditivesIds);
		Set<Integer> purchasematerialsIds = new HashSet<Integer>();
		for (Purchasematerial obj : unit.getPurchasematerialsForUnit()) {

			purchasematerialsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("purchasematerialsIds", purchasematerialsIds);

		return objectReferencedSetMap;
	}

	public Map<String, ?> loadUnitClassReferencedSet(Unit unit) {
		HashMap<String, Object> classReferencedSetMap = new HashMap<>();
		classReferencedSetMap.put("additiveaddresss", additiveaddressDAO.findAllAdditiveaddresss());
		classReferencedSetMap.put("detectdetails", detectdetailDAO.findAllDetectdetails());
		classReferencedSetMap.put("detectfeatures", detectfeatureDAO.findAllDetectfeatures());
		classReferencedSetMap.put("detectstandards", detectstandardDAO.findAllDetectstandards());
		classReferencedSetMap.put("expires", expireDAO.findAllExpires());
		classReferencedSetMap.put("featurestandards", featurestandardDAO.findAllFeaturestandards());
		classReferencedSetMap.put("foodbatchs", foodbatchDAO.findAllFoodbatchs());
		classReferencedSetMap.put("foodbatchfillers", foodbatchfillerDAO.findAllFoodbatchfillers());
		classReferencedSetMap.put("foodsaleaddresss", foodsaleaddressDAO.findAllFoodsaleaddresss());
		classReferencedSetMap.put("materialaddresss", materialaddressDAO.findAllMaterialaddresss());
		classReferencedSetMap.put("packingmethods", packingmethodDAO.findAllPackingmethods());
		classReferencedSetMap.put("processmethods", processmethodDAO.findAllProcessmethods());
		classReferencedSetMap.put("purchaseadditives", purchaseadditiveDAO.findAllPurchaseadditives());
		classReferencedSetMap.put("purchasematerials", purchasematerialDAO.findAllPurchasematerials());

		return classReferencedSetMap;
	}

	public boolean isEquals(Unit unit, Object obj) {
		if (obj == unit)
			return true;
		if (!(obj instanceof Unit))
			return false;
		Unit comparedUnit = (Unit) obj;
		if (!CheckPropertyEqual(unit.getName(), comparedUnit.getName())) {
			return false;
		}
		if (!CheckPropertyEqual(unit.getType(), comparedUnit.getType())) {
			return false;
		}
		return true;
	}

	public static <T> boolean CheckPropertyEqual(T originProperty, T comparedProperty) {
		// 基本类型经过参数传递后会自动装箱
		String[] className = originProperty.getClass().getName().split("\\.");
		if (className[0].equals("java") && className[1].equals("math")) {
			return ((Comparable) originProperty).compareTo(comparedProperty) == 0 ? true : false;
		} else {
			return originProperty.equals(comparedProperty);
		}
	}
}

